//
//  AccountingCategory.swift
//  KoiAccounting
//
//  Created by 纪洪文 on 16.03.25.
//

import Foundation
import GRDB

struct AccountingCategory : RecordSyncable, Codable, Identifiable, Equatable, Hashable, FetchableRecord, MutablePersistableRecord {
    var id:Int64?
    var cid:String?
    var name:String?
    var type:String?
    var icon:String?
    var orderId:Int?
    var bookId:String?
    var uid:String?
    var parentId:String?
    var createTime:String?
    var updateTime:String?
    var isDel:Int? = 0
    var dataFlag:Int? = 0
    var sv:Int? = 0
    
    // 记录一下二级类别的展开状态
    var isExpand = false
    var isSelected = false
    var hasSubCategory = false
    var hasRecord = false
    var isDisable = false
    var subCategoryList = Array<AccountingCategory>()
    
    static let addSubItem = AccountingCategory(cid: "add_sub", name: "添加子类")
    static let settingItem = AccountingCategory(cid: "setting", name: "设置")
    static let iconItem = AccountingCategory(cid: "icon", name: "icon")

    static func == (lhs:AccountingCategory, rhs:AccountingCategory) -> Bool {
        return lhs.cid == rhs.cid
                && lhs.icon == rhs.icon
                && lhs.name == rhs.name
                && lhs.orderId == rhs.orderId
                && lhs.parentId == rhs.parentId
                && lhs.hasRecord == rhs.hasRecord
    }
    
    // 鉴于 func == 同时用于视图比较，所以只能新增 compare 方法用于数据比较
    func compare(other: AccountingCategory) -> Bool {
        return self.cid == other.cid
    }
    
    enum CodingKeys: String, CodingKey {
            case id, cid, name, type, icon, uid, orderId = "order_id", bookId = "book_id", parentId = "parent_id", createTime = "create_time", updateTime = "update_time", isDel = "is_del", dataFlag = "data_flag", sv
        }
    
    // 定义数据库表
    static let databaseTableName = "accounting_category"

    enum Columns: String, ColumnExpression {
        case id, cid, name, type, icon, orderId = "order_id", bookId = "book_id", uid, parentId = "parent_id", createTime = "create_time", updateTime = "update_time", isDel = "is_del", dataFlag = "data_flag", sv
    }
    
    // 实现数据库持久化方法
    mutating func didInsert(with rowID: Int64, for column: String?) {
        id = rowID
    }
    
    mutating func makeUpdate() {
        self.dataFlag = DataFlag.update.rawValue
        updateTime = Date().toISODateString()
    }
    
    mutating func makeDelete() {
        self.dataFlag = DataFlag.delete.rawValue
        self.isDel = 1
        updateTime = Date().toISODateString()
    }
    
    mutating func changeToFirst() {
        self.parentId = nil
    }
    
    mutating func changeToSub(parentId: String) {
        self.parentId = parentId
    }
    
    func getCategoryType() -> CategoryType {
        return CategoryType.getType(type: type.orEmpty)
    }
    
    func isTopCategory() -> Bool {
        return parentId == nil
    }
    
    func isSubCategory() -> Bool {
        return parentId != nil
    }
    
    static func createTable(dbQueue: DatabaseQueue) {
        do {
            try dbQueue.write{ db in
                if (try db.tableExists(databaseTableName)) {
                    logger.info("table already exists \(databaseTableName)")
                } else {
                    try db.create(table: databaseTableName) { t in
                        t.autoIncrementedPrimaryKey(Columns.id.rawValue)
                        t.column(Columns.cid.rawValue, .text)
                        t.column(Columns.name.rawValue, .text)
                        t.column(Columns.type.rawValue, .text)
                        t.column(Columns.icon.rawValue, .text)
                        t.column(Columns.orderId.rawValue, .integer)
                        t.column(Columns.bookId.rawValue, .text)
                        t.column(Columns.uid.rawValue, .text)
                        t.column(Columns.parentId.rawValue, .text)
                        t.column(Columns.createTime.rawValue, .text)
                        t.column(Columns.updateTime.rawValue, .text)
                        t.column(Columns.isDel.rawValue, .integer)
                        t.column(Columns.sv.rawValue, .integer)
                        t.column(Columns.dataFlag.rawValue, .integer)
                    }
                    try db.execute(sql: "CREATE UNIQUE INDEX unique_index_cid_book_id_uid ON accounting_category (cid, book_id, uid)")
                }
            }
        } catch {
            logger.error("create accounting_category table fail \(error)")
        }
    }
    
    func getIconAssetUri()->String {
        return CategoryIcon.getIconAssetUri(iconUrl: icon.orEmpty)
    }
    
    func getNameWithSubCategory(subName: String?) -> String {
        if (subName != nil) {
            return name.orEmpty + "-" + subName.orEmpty
        } else {
            return name.orEmpty
        }
    }
    
    static func generateCid() -> String {
        return "koi_c_\(ShortUUID().generate())"
    }
}
